package game;

import java.awt.Color;
import java.io.File;
import java.util.Observer;
import java.util.Set;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

/**
 * My singleton
 * @author Substandard
 *
 */
public final class Game 
{
	public static final String DISK_GAME_LEVEL_PATH = "c:\\stuff\\temp\\game.txt";

	private static DrawableRectangleImpl selectedComp;
	private static Observer interestedObserver;
	private static IGameLevel gameLevel = new GameLevelImpl();

	//singleton - private constructor
	private Game()
	{
		;
	}

	public static synchronized void saveGameLevelToDisk()
	{
		//run on a new thread, don't block the GUI thread when saving/loading
		Thread t = new Thread()
		{
			@Override
			public void run()
			{
				File file = null;
				try
				{
					file = new File(DISK_GAME_LEVEL_PATH);
					JAXBContext jaxbContext = JAXBContext.newInstance(GameLevelImpl.class);
					Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
					// output pretty printed
					jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			 
					jaxbMarshaller.marshal(gameLevel(), file);
					jaxbMarshaller.marshal(gameLevel(), System.out);
				}
				catch(Exception exc)
				{
					System.out.println(exc);
				}
			}
		};
		t.start();
	}

	public static synchronized void loadGameLevelFromDisk()
	{
		//run on a new thread, don't block the GUI thread when saving/loading
		Thread t = new Thread()
		{
			@Override
			public void run()
			{
				File file;
				try
				{
					file = new File(DISK_GAME_LEVEL_PATH);
					JAXBContext jaxbContext = JAXBContext.newInstance(GameLevelImpl.class);
					Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
					gameLevel( (GameLevelImpl)jaxbUnmarshaller.unmarshal(file) );

				}
				catch(Exception exc)
				{
					System.out.println(exc);
				}
			}
		};
		t.start();
	}

	//accessors
	public static synchronized IGameLevel gameLevel()
	{
		return gameLevel;
	}

	public static synchronized void gameLevel(IGameLevel gameLevel)
	{
		Game.gameLevel = gameLevel;
	}

	public static synchronized IDrawableRectangle selectedComp(IDrawableRectangle newSelectedComponent)
	{
		//make white the old selected component
		if (selectedComp() != null && selectedComp() != newSelectedComponent)
		{
			selectedComp.color(Color.WHITE);
		}
		selectedComp = (DrawableRectangleImpl) newSelectedComponent;
		if (selectedComp != null)
		{
			selectedComp.addObserver(interestedObserver() );
			//make black the new selected component
			selectedComp.color(Color.BLACK);
		}
		
		return selectedComp;
	}
	
	public static synchronized IDrawableRectangle selectedComp()
	{
		return selectedComp;
	}

	public static boolean noComponentSelected()
	{
		return selectedComp() == null;
	}

	public static synchronized Observer interestedObserver(Observer interestedObserver)
	{
		Game.interestedObserver = interestedObserver;
		return interestedObserver;
	}
	
	public static synchronized Observer interestedObserver()
	{
		return interestedObserver;
	}
	
	public static synchronized Set<IDrawableRectangle> gameComponents()
	{
		return gameLevel().getPlatforms();
	}
	
	public static synchronized Set<IDrawableRectangle> gameComponents(Set<IDrawableRectangle> gameComponents)
	{
		gameLevel().setPlatforms(gameComponents);
		return gameComponents();
	}
}
